/**
 * 运行时决定线程数量
 * 线程识别
 * 
 * std::accumulate  累加，或根据op 向右折叠
 * std::distance
 * std::thread:hardware_concurrency
 * std::advance 将迭代器向前或向后推进 N 个位置
 */

#include <thread>
#include <numeric>
#include <algorithm>
#include <functional>
#include <vector>
#include <iostream>

//积木
template<typename Iterator,typename T>
struct accumulate_block
{
    void operator()(Iterator first,Iterator last,T& result)
    {
        result=std::accumulate(first,last,result);
    }
};
//平行累积
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
    unsigned long const length=std::distance(first,last);

    if(!length)
        return init;

    unsigned long const min_per_thread=25;
    unsigned long const max_threads=
        (length+min_per_thread-1)/min_per_thread; //预计线程个数

    unsigned long const hardware_threads=
        std::thread::hardware_concurrency();  //查看硬件支持线程个数

    unsigned long const num_threads=
        std::min(hardware_threads!=0?hardware_threads:2,max_threads); //确定线程个数

    unsigned long const block_size = length / num_threads; //计算线程需要计算的块的大小

    std::cout << "length " << length << std::endl;
    std::cout << "min_per_thread " << min_per_thread << std::endl;
    std::cout << "max_threads " << max_threads << std::endl;
    std::cout << "hardware_threads " << hardware_threads << std::endl;
    std::cout << "num_threads " << num_threads << std::endl;
    std::cout << "block_size " << block_size << std::endl;
    std::vector<T> results(num_threads); //结果集
    std::vector<std::thread>  threads(num_threads-1); //确定的线程数需要少一个，因为已经有一个主线程启动了

    Iterator block_start=first;
    for(unsigned long i=0;i<(num_threads-1);++i)
    {
        Iterator block_end=block_start;
        std::advance(block_end,block_size);
        threads[i]=std::thread(
            accumulate_block<Iterator,T>(),
            block_start,block_end,std::ref(results[i]));
        block_start=block_end;
    }
    accumulate_block<Iterator,T>()(block_start,last,results[num_threads-1]);
    
    std::for_each(threads.begin(),threads.end(),
        std::mem_fn(&std::thread::join));

    return std::accumulate(results.begin(),results.end(),init);  // 将所有结果进行累加
}

std::thread::id master_thread;
void do_something()
{
    std::cout << "do_something() is running "<< std::endl;
}
void thread_run()
{
    std::thread::id thread_id = std::this_thread::get_id();  //线程内获取 标识
    std::cout << "thread_run() thread_id "<< thread_id << std::endl;
    if(thread_id==master_thread)
        do_something();
    return;
}
int main()
{
    int64_t time1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::vector<int> vi;
    for(int i=0;i<10000000;++i)
    {
        vi.push_back(10);
    }
    int sum=parallel_accumulate(vi.begin(),vi.end(),0);
    std::cout<<"sum="<<sum<<std::endl;
    int64_t time2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout << "time " << time2-time1 << std::endl;
    master_thread = std::this_thread::get_id();

    std::cout << "main() master_thread "<< master_thread << std::endl;
    std::thread t(thread_run);
    t.join();  //如果没有加入线程，程序将运行异常，核心转储
     
}
